package com.yue.yadmin.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

/**
 * 自动生成工具类
 * @author liaoxinyue
 * 2018年3月30日 下午2:42:10
 * 
 */
public class GenerateUtils {
	private static Logger logger = LoggerFactory.getLogger(GenerateUtils.class);
	
	public static void main(String[] args) {
		GenerateEnumEntity entity = new GenerateEnumEntity();
		entity.setAuthor("廖欣跃");
		entity.setEnumMsg("字典代码   menu-icon:菜单icon ");
		entity.setEnumName("EnumDictCode");
		entity.setPackageName("com.yue.yadmin.enums");
		entity.setFields(new String[]{"code","desc"});
		entity.setFieldValues(new Object[][]{new Object[]{"menu-icon","菜单icon"}	});
		entity.setEnumValueNames(new String[]{"MENU_ICON"});
		System.out.println(1+":"+generateEnum(entity));
//		System.out.println(2+":"+generateEnum1("EnumCode",new Object[]{0,"成功"},new Object[]{1,"失败"}));
//		System.out.println(generateEnum2("EnumTest2", new Object[]{1,2,3,4},new Object[]{"aaa","ca","sss","bb"}));
	}
	
	/**
	 * 生成枚举
	 * @param enumName 枚举名
	 * @param enums 传入枚举值  例：{1,"描述"},{2,"描述"}
	 * @return
	 */
	public static Result generateEnum1(String enumName,Object[]...enums){
		GenerateEnumEntity entity = new GenerateEnumEntity();
		entity.setEnumName(enumName);
		entity.setFieldValues(enums);
		return generateEnum(entity);
	}
	/**
	 * 生成枚举
	 * @param enumName 枚举名
	 * @param enums 传入枚举值  例：{1,2},{"描述1","描述2"}
	 * @return
	 */
	public static Result generateEnum2(String enumName,Object[]...enums){
		GenerateEnumEntity entity = new GenerateEnumEntity();
		entity.setEnumName(enumName);
		List<ArrayList<Object>> list = new ArrayList<ArrayList<Object>>();
		for(int i=0;i<enums.length;i++){
			for(int j=0;j<enums[i].length;j++){
				if(i==0){
					list.add(new ArrayList<Object>());
				}
				ArrayList<Object> subList = list.get(j);
				subList.add(enums[i][j]);
				list.set(j, subList);
			}
		}
		List<Object[]> newList = new ArrayList<Object[]>();
		for(List<Object> subList:list){
			newList.add(subList.toArray());
		}
		entity.setFieldValues(newList.toArray(new Object[][]{}));
		return generateEnum(entity);
	}
	
	/**
	 * 根据生成枚举实体生成枚举
	 * @param entity
	 * @return
	 */
	public static Result generateEnum(GenerateEnumEntity entity){
		//值校验
		if(StringUtils.isBlank(entity.getEnumName())){
			return new Result(-1,"枚举名必填");
		}else if(entity.getFieldValues()==null||entity.getFieldValues().length<=0||entity.getFieldValues()[0].length<=0){
			return new Result(-1,"字段值必填");
		}else if(entity.getEnumValueNames()!=null&&entity.getEnumValueNames().length!=entity.getFieldValues().length){
			return new Result(-1,"枚举值必须相等");
		}else if(entity.getFields()!=null&&entity.getFields().length!=entity.getFieldValues()[0].length){
			return new Result(-1,"字段名跟字段值必须相等");
		}
		//默认值设置
		if(StringUtils.isBlank(entity.getPackageName())){
			//无则传入当前工具类包名
			entity.setPackageName(GenerateUtils.class.getPackage().getName());
		}
		if(entity.getEnumValueNames()==null||entity.getEnumValueNames().length<=0||entity.getFields()==null||entity.getFields().length<=0){
			List<String> enumValueNameList = new ArrayList<String>();
			List<Object> fieldList = new ArrayList<Object>();
			int limitLength = 0;
			for(int i=0;i<entity.getFieldValues().length;i++){
				Object[] objs = entity.getFieldValues()[i];
				if(entity.getEnumValueNames()==null||entity.getEnumValueNames().length<=0){
					enumValueNameList.add("ENUM"+i);
				}
				if(i==0){
					limitLength = objs.length;
				}else if(limitLength!=objs.length){
					return new Result(-1,"字段值格式不正确");
				}
				for(int j=0;j<objs.length;j++){
					if(i==0&&(entity.getFields()==null||entity.getFields().length<=0)){
						fieldList.add("field"+j);
					}
				}
			}
			String[] model = {};
			if(enumValueNameList.size()>0)entity.setEnumValueNames(enumValueNameList.toArray(model));
			if(fieldList.size()>0)entity.setFields(fieldList.toArray(model));
		}
		if(StringUtils.isBlank(entity.getFilePath())){
			//利用System.getProperty()函数获取当前路径： user.dir指定了当前的路径 
			entity.setFilePath(String.format("%s%ssrc%smain%sjava%s%s%s%s.java", 
					System.getProperty("user.dir"),File.separator,File.separator,File.separator,File.separator,
					entity.getPackageName().replace(".", File.separator),File.separator,entity.getEnumName()));
		}
		//生成枚举内容
		String content = null;
		try {
			content = generateEnumContent(entity);
		} catch (Exception e) {
			return new Result(-2,e.getMessage());
		}
		//创建枚举
		try {
			createFile(content, entity.getFilePath());
		} catch (Exception e) {
			return new Result(-3,e.getMessage());
		}
		return new Result(0,"生成枚举成功");
	}
	
	/**
	 * 生成枚举内容
	 * @param entity
	 * @return
	 * @throws Exception
	 */
	private static String generateEnumContent(GenerateEnumEntity entity) throws Exception{
		String space = "	";
		StringBuffer sb = new StringBuffer();
		if(StringUtils.isNotBlank(entity.getPackageName()))sb.append(String.format("package %s;\n", entity.getPackageName()));
		sb.append("/**\n");
		if(StringUtils.isNotBlank(entity.getEnumMsg()))sb.append(String.format(" * %s\n", entity.getEnumMsg()));
		if(StringUtils.isNotBlank(entity.getAuthor()))sb.append(String.format(" * %s\n", entity.getAuthor()));
		sb.append(String.format(" * %s\n", new Date().toString()));
		sb.append(" */\n");
		sb.append(String.format("public enum %s {\n", entity.getEnumName()));
		try {
			if(entity.getFieldValues().length>0&&entity.getFields().length>0&&entity.getFieldValues()[0].length==entity.getFields().length){
				StringBuffer attribute = new StringBuffer();
				StringBuffer setGetMethod = new StringBuffer();
				StringBuffer constructor = new StringBuffer(String.format("%sprivate %s(",space,entity.getEnumName()));
				StringBuffer constructorAttribute = new StringBuffer();
				StringBuffer method = new StringBuffer(String.format("%s/**\n%s * 查找枚举,不存在返回null\n%s */\n%spublic static %s getEnum(", space,space,space,space,entity.getEnumName()));
				StringBuffer methodContent = new StringBuffer(String.format("%s%sfor(%s e:values()){\n%s%s%sif(", space,space,entity.getEnumName(),space,space,space));
				for(int i=0;i<entity.getFieldValues().length;i++){
					Object[] objs = entity.getFieldValues()[i];
					StringBuffer placePosi = new StringBuffer();
					List<Object> params = new ArrayList<Object>();
					params.add(space);
					params.add(entity.getEnumValueNames()[i]);
					for(int j = 0;j<objs.length;j++){
						placePosi.append("%s");
						if(j<objs.length-1)placePosi.append(",");
						params.add(getParam(objs[j]));
						if(i==0){
							attribute.append(String.format("%sprivate %s %s;\n",space, getType(objs[j]),entity.getFields()[j]));
							setGetMethod.append(String.format("%spublic void set%s(%s %s){\n%s%sthis.%s=%s;\n	}\n",space, firstUpCase(entity.getFields()[j]),getType(objs[j]),entity.getFields()[j],space,space,entity.getFields()[j],entity.getFields()[j]));
							setGetMethod.append(String.format("%spublic %s get%s(){\n%s%sreturn %s;\n	}\n", space,getType(objs[j]),firstUpCase(entity.getFields()[j]),space,space,entity.getFields()[j]));
							constructor.append(String.format("%s %s%s",getType(objs[j]),entity.getFields()[j],j<(objs.length-1)?",":"){\n%s%s}\n"));
							constructorAttribute.append(String.format("%s%sthis.%s=%s;\n", space,space,entity.getFields()[j],entity.getFields()[j]));
							method.append(String.format("%s %s%s",getPackageType(objs[j]),entity.getFields()[j],j<(objs.length-1)?",":"){\n%s%s}\n"));
							methodContent.append(String.format("(%s!=null&&e.get%s()%s)%s",entity.getFields()[j],firstUpCase(entity.getFields()[j]),getCompare(objs[j],entity.getFields()[j]),j<(objs.length-1)?"||":String.format("){\n%s%s%s%sreturn e;\n%s%s%s}\n%s%s}\n%s%sreturn null;\n", space,space,space,space,space,space,space,space,space,space,space)));
						}
					}
					sb.append(String.format("%s/**\n%s *%s\n%s */\n", space,space,JSONObject.toJSONString(objs),space));
					params.add(i<(entity.getFieldValues().length-1)?",":";");
					String str = "%s%s("+placePosi.toString()+")%s\n";
					sb.append(String.format(str, params.toArray()));
				}
				sb.append(attribute.toString());
				sb.append(setGetMethod.toString());
				sb.append(String.format(constructor.toString(), constructorAttribute.toString(),space));
				sb.append(String.format(method.toString(), methodContent.toString(),space));
			}
		} catch (Exception e) {
			String msg = String.format("格式不正确：%s", e.getMessage());
			logger.error(msg);
			throw new Exception(msg);
		}
		sb.append("}\n");
		return sb.toString();
	}
	
	/**
	 * 根据值获取比较方式 
	 * @param obj
	 * @param field
	 * @return
	 */
	private static String getCompare(Object obj,String field){
		if(obj instanceof String){
			return String.format(".equals(%s)", field);
		}else{
			return String.format("==%s", field);
		}
	}
	
	/**
	 * 根据值获取参数类型
	 * @param obj
	 * @return
	 */
	private static String getType(Object obj){
		if(obj instanceof String){
			return "String";
		}else if(obj instanceof Integer){
			return "int";
		}else if(obj instanceof Long){
			return "long";
		}else if(obj instanceof Double){
			return "double";
		}else if(obj instanceof Float){
			return "float";
		}else if(obj instanceof Boolean){
			return "boolean";
		}else if(obj instanceof Character){
			return "char";
		}else if(obj instanceof Short){
			return "short";
		}else{
			return "String";
		}
	}
	
	/**
	 * 根据值获取参数封装类型
	 * @param obj
	 * @return
	 */
	private static String getPackageType(Object obj){
		if(obj instanceof String){
			return "String";
		}else if(obj instanceof Integer){
			return "Integer";
		}else if(obj instanceof Long){
			return "Long";
		}else if(obj instanceof Double){
			return "Double";
		}else if(obj instanceof Float){
			return "Float";
		}else if(obj instanceof Boolean){
			return "Boolean";
		}else if(obj instanceof Character){
			return "Character";
		}else if(obj instanceof Short){
			return "Short";
		}else{
			return "String";
		}
	}
	
	/**
	 * 获取参数
	 * @param obj
	 * @return
	 */
	private static Object getParam(Object obj){
		if(obj instanceof String){
			return "\""+obj+"\"";
		}else{
			return obj;
		}
	}
	
	/**
	 * 首字母大写，其余字母小写
	 * @param str
	 * @return
	 */
	private static String firstUpCase(String str){
		str = str.toLowerCase();
		String firstStr = str.substring(0,1);
		return str.replaceFirst(firstStr, firstStr.toUpperCase());
	}
	
	/**
	 * 创建文件
	 * @param content 内容
	 * @param path 地址
	 * @throws Exception
	 */
	private static void createFile(String content,String path) throws Exception{
		File file =new File(path);
		OutputStream output = null;
		try {
			if(file.getParentFile().isDirectory()){
				if(!file.isFile()){
					file.createNewFile();
				}
				output = new FileOutputStream(file);
				output.write(content.getBytes());
			}else{
				throw new Exception("地址不存在");
			}
		} catch (Exception e) {
			String error = "创建文件失败："+e.getMessage();
			logger.error(error);
			throw new Exception(error);
		} finally {
			if(output!=null)
				try {
					output.close();
				} catch (IOException e) {
					logger.error("关闭流失败："+e.getMessage());
				}
		}
	}
}
